package com.xcc.netty.socket.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author frosty
 * @description
 * @date 2019-12-31 31:10:33
 */


public class NIOServer {


    public static void main(String[] args) throws Exception {
        //创建ServerSocketChannel   ->SocketChannel
        ServerSocketChannel ssc = ServerSocketChannel.open(); //服务器ServerSocketChannel 也要注册到selector中

        //创建一个Selector 对象
        Selector selector = Selector.open();
        //绑定一个端口   在服务器监听
        ssc.socket().bind(new InetSocketAddress(8761));
        //设置为非阻塞
        ssc.configureBlocking(false);

        //将serversocketChannel  注册到selector中  关心事件为 OP_ACCEPT  连接事件
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        //循环等待客户端连接
        while (true) {
            if (selector.select(1000) == 0) { //等待一秒    0表示没有事件发生
                System.out.println("server  wait  1 second   not connection");
                continue;
            }
            //1如果有事件  则 大于0  就获取有事键发生的selectKey集合
            //2   selector.selectedKeys();   表示已经获取关注事件的集合
            //通过 selectionKeys 反向获取通道
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            System.out.println("selectionKeys"+selectionKeys.size());

            //便利  selectionKeys 使用迭代器
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
            while (keyIterator.hasNext()) {
                //获取到SelectionKey
                SelectionKey key = keyIterator.next();
                //根据key  对对应事件做处理
                if (key.isAcceptable()) {  //如果是一个OP_ACCEPT  有新的客户端连接
                    //产生一个socketChannel  本来 accept(); 方法是阻塞的  但是 这里是已经接到一个连接请求  在 执行方法  所以不是阻塞的
                    SocketChannel socketChannel = ssc.accept();
                    socketChannel.configureBlocking(false);  //设置为非阻塞  客户端一样
                    //将 socketChannel 注册到 selector 中  选择 事件  并且 绑定一个buffer  客户端  连接请求  到此完成
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("connection success");
                }
                if (key.isReadable()) {  //读的事件
                    //得到socketChannel  强转类型
                    SocketChannel channel = (SocketChannel) key.channel();

                    //得到byffer 强转类型
                 //   ByteBuffer buffer = (ByteBuffer) key.attachment();
                      ByteBuffer buffer = ByteBuffer.allocate(3);
                     StringBuffer sb=new StringBuffer();
                     //读取有问题?
                      while ((channel.read(buffer))!=-1){
                               sb.append(buffer);
                             System.out.println(new String(buffer.array()));
                          buffer.clear();
                      }

                      if(channel.read(buffer)==-1){
                          channel.close();
                      }

                    System.out.println("form client message:"+sb);
                }
                //在集合中删除当前key
                  //一一定要移除  免得多线程重复
                keyIterator.remove();

            }

        }


    }
}
